package com.xyy.saas.payment.api.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.pingan.openbank.api.sdk.client.ApiClient;
import com.pingan.openbank.api.sdk.common.http.HttpResult;
import com.pingan.openbank.api.sdk.entity.SdkRequest;
import com.xyy.saas.payment.adpater.abchinaLoan.core.req.ApplyH5Dto;
import com.xyy.saas.payment.adpater.abchinaLoan.core.req.QueryLoanDto;
import com.xyy.saas.payment.adpater.abchinaLoan.core.resp.QueryLoanStatusResp;
import com.xyy.saas.payment.adpater.abchinaLoan.service.AbchinaLoanService;
import com.xyy.saas.payment.adpater.impl.AbchinaLoanAdapter;
import com.xyy.saas.payment.adpater.impl.JdCreditAdapter;
import com.xyy.saas.payment.adpater.impl.PinganAdapter;
import com.xyy.saas.payment.adpater.impl.XydLoanAdapter;
import com.xyy.saas.payment.adpater.jdCredit.service.UnionLoginService;
import com.xyy.saas.payment.adpater.pingan.PinganMethod;
import com.xyy.saas.payment.adpater.xydLoan.core.dto.XydAuthCreditDto;
import com.xyy.saas.payment.adpater.xydLoan.core.dto.XydCreditResultDto;
import com.xyy.saas.payment.adpater.xydLoan.core.req.XydAccountBalanceReq;
import com.xyy.saas.payment.cores.vo.XydGetFileDto;
import com.xyy.saas.payment.adpater.xydLoan.core.req.XydAuthCreditReq;
import com.xyy.saas.payment.adpater.xydLoan.core.req.XydGetFileReq;
import com.xyy.saas.payment.adpater.xydLoan.core.resp.XydAuthCreditResp;
import com.xyy.saas.payment.adpater.xydLoan.service.XydLoanService;
import com.xyy.saas.payment.common.exception.PayBizException;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.api.PaymentLoanApi;
import com.xyy.saas.payment.cores.enums.*;
import com.xyy.saas.payment.cores.param.*;
import com.xyy.saas.payment.cores.vo.*;
import com.xyy.saas.payment.cores.vo.jd.JdCreditUnionLoginVo;
import com.xyy.saas.payment.dao.model.PayFinanceApply;
import com.xyy.saas.payment.query.core.service.QueryTradeService;
import com.xyy.saas.payment.service.PayAccountService;
import com.xyy.saas.payment.service.PayResultOrderService;
import com.xyy.saas.payment.service.PinganLoanFinanceApplyService;
import com.xyy.saas.payment.util.AmountCastUtil;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.saas.payment.util.JSONUtils;
import com.xyy.saas.payment.util.LeafUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 银行贷款融资相关接口 实现
 *
 * @author huguangming
 * @since 2022/10/9
 */
@Slf4j
@Service(version = "1.0.0")
public class PaymentLoanApiImpl implements PaymentLoanApi {

    // 实例化平安API对象
    private static ApiClient apiClient = ApiClient.getInstance("config/config-4294-test.properties");
    @Value("${pinganCreditLoginCheckUrl}")
    private String pinganCreditLoginCheckUrl;
    @Resource
    private LeafUtil leafUtil;

    @Resource
    private PayResultOrderService payResultOrderService;

    @Resource
    private PinganLoanFinanceApplyService pinganLoanFinanceApplyService;

    @Resource
    private PayAccountService payAccountService;

    @Resource
    private PinganAdapter pinganAdapter;

    @Resource
    private JdCreditAdapter jdCreditAdapter;

    @Resource
    private AbchinaLoanAdapter abchinaLoanAdapter;
    @Resource
    private XydLoanAdapter xydLoanAdapter;
    @Autowired
    private QueryTradeService queryTradeService;
    @Autowired
    private UnionLoginService unionLoginService;
    @Autowired
    private AbchinaLoanService abchinaLoanService;
    @Autowired
    private XydLoanService xydLoanService;

    @Override
    public ResultVO<PinganLoanPreApplyResultVo> payFiancePreApply(PinganLoanPreApplyParam param, String sign) {

        log.info("PaymentLoanApiImpl.payFiancePreApply param:{}", JSONUtils.toJSON(param));

        // 10.1 贷款申请接口
        if (param == null || StringUtils.isBlank(param.getBusinessUserId())) {
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
        }

        JSONObject requestParam = new JSONObject();
        String thirdApplyNo = leafUtil.getSnowflakeId();
        try {

            PayFinanceApply record = new PayFinanceApply();
            record.setThirdApplyNo(thirdApplyNo);
            record.setBusinessUserId(param.getBusinessUserId());
            record.setBusinessUserName(param.getBusinessUserName());
            record.setBusinessType(param.getBusinessType());
            record.setApplyStatus(PinganLoanApplyStatusEnum.UN_PRE_APPLY.getCode());
            record.setCreateTime(new Date());
            record.setUpdateTime(new Date());

            int result = pinganLoanFinanceApplyService.insert(record);
            log.info("PaymentLoanApiImpl.payFiancePreApply pinganLoanFinanceApplyService.insert(record) result={}", result);
            if (result != 1) {
                return ResultVO.createError(ResultCodeEnum.DATABASE_ERROR);
            }

            // 1.组装请求参数
            requestParam.put("ThirdApplyNo", thirdApplyNo);
            requestParam.put("ChannelCode", ApolloUtil.getProperty("pingan.ChannelCode"));
            requestParam.put("ProjectCode", ApolloUtil.getProperty("pingan.ProjectCode"));
            requestParam.put("ProductCode", ApolloUtil.getProperty("pingan.ProductCode"));
            requestParam.put("MrchCode", ApolloUtil.getProperty("pingan.MrchCode"));

            String accountId = payAccountService.getAccountIdByBusiness(BusinessIdTypeEnum.EC.getType(), param.getBusinessUserId());
            if (StringUtils.isBlank(accountId)) {
                log.info("PaymentLoanApiImpl.payFiancePreApply accountId is blank");
                return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
            }
            requestParam.put("MemberCode", accountId);
            requestParam.put("UserId", param.getBusinessUserId());
            requestParam.put("EnterpriseName", param.getBusinessUserName());

            // 2.请求体
            SdkRequest sdkRequest = new SdkRequest();
            sdkRequest.setInterfaceName("V1.0/" + PinganMethod.LOAN_PRE_APPLY.getMethodName());
            sdkRequest.setBody(requestParam);

            // 3.发送请求
            log.info("PaymentLoanApiImpl#payFiancePreApply request:{}", JSONUtils.toJSON(requestParam));
            HttpResult response = apiClient.invoke(sdkRequest);
            log.info("PaymentLoanApiImpl#payFiancePreApply request:{} response:{}", JSONUtils.toJSON(requestParam), JSONUtils.toJSON(response));

            // 4.通信状态判断
            if (response == null || !response.isSuccess()) {
                log.error("PaymentLoanApiImpl#payFiancePreApply invoke pingan error, response isSuccess=false");
                return ResultVO.createError(ResultCodeEnum.PINGAN_SYSTEM_ERROR);
            }

            PinganAdapter.PinganResponse pinganResponse = null;
            try {
                pinganResponse = PinganAdapter.PinganResponse.parse(response.getData());
                log.info("PaymentLoanApiImpl#payFiancePreApply pinganResponse={}", JSON.toJSONString(pinganResponse));
            } catch (PaymentException e) {
                log.error("PaymentLoanApiImpl#payFiancePreApply invoke pingan error", e);
                return ResultVO.createError(ResultCodeEnum.PINGAN_SYSTEM_ERROR);
            }

            PayFinanceApply payFinanceApplyQueryResult = pinganLoanFinanceApplyService.selectByThirdApplyNo(thirdApplyNo);
            PayFinanceApply payFinanceApplyUpdate = new PayFinanceApply();
            payFinanceApplyUpdate.setId(payFinanceApplyQueryResult.getId());
            payFinanceApplyUpdate.setApplyStatus(PinganLoanApplyStatusEnum.PRE_APPLY_SUCCESS.getCode());
            pinganLoanFinanceApplyService.updateByPrimaryKeySelective(payFinanceApplyUpdate);

            return ResultVO.createSuccess(new PinganLoanPreApplyResultVo(thirdApplyNo, requestParam.getString("ChannelCode")));
        } catch (Exception ex) {
            log.error("PaymentLoanApiImpl#payFiancePreApply error, param=" + JSONUtils.toJSON(requestParam) + ", errorMsg=" + ex.getMessage(), ex);
            return ResultVO.createError(ResultCodeEnum.PINGAN_SYSTEM_ERROR);
        }
    }

    @Override
    public ResultVO<PinganLoanQueryApplyStatusVo> payFianceApplyStatus(PinganLoanQueryApplyStatusParam param, String sign) {

        log.info("PaymentLoanApiImpl.payFianceApplyStatus param:{}", JSONUtils.toJSON(param));

        // 10.5 融资状态查询接口
        if (param == null || StringUtils.isBlank(param.getThirdApplyNo())) {
            log.error("PaymentLoanApiImpl#payFianceApplyStatus param is null");
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
        }

        String thirdApplyNo = param.getThirdApplyNo();

        PayFinanceApply payFinanceApply = pinganLoanFinanceApplyService.selectByThirdApplyNo(thirdApplyNo);
        if (payFinanceApply == null) {
            log.error("PaymentLoanApiImpl#payFianceApplyStatus error, param=" + JSONUtils.toJSON(param) + ", errorMsg=" + "支付平台申请编号不存在");
            return ResultVO.createError("支付平台申请编号不存在");
        }

        // 1.组装请求参数
        JSONObject requestParam = new JSONObject();
        requestParam.put("ThirdApplyNo", thirdApplyNo);
        requestParam.put("ProjectCode", ApolloUtil.getProperty("pingan.ProjectCode"));
        requestParam.put("ChannelCode", ApolloUtil.getProperty("pingan.ChannelCode"));

        // 2.请求体
        SdkRequest sdkRequest = new SdkRequest();
        sdkRequest.setInterfaceName("V1.0/" + PinganMethod.LOAN_APPLY_STATUS.getMethodName());
        sdkRequest.setBody(requestParam);

        // 3.发送请求
        HttpResult response = null;
        try {
            response = apiClient.invoke(sdkRequest);
        } catch (Exception e) {
            log.error("PaymentLoanApiImpl#payFianceApplyStatus error request:{}", JSONUtils.toJSON(requestParam), e);
            return ResultVO.createError(ResultCodeEnum.PINGAN_SYSTEM_ERROR);
        }
        log.info("PaymentLoanApiImpl#payFianceApplyStatus request:{} response:{}", JSONUtils.toJSON(requestParam), JSONUtils.toJSON(response));

        // 4.通信状态判断
        if (response == null || !response.isSuccess()) {
            log.error("PaymentLoanApiImpl#payFianceApplyStatus invoke pingan error, response isSuccess=false");
            return ResultVO.createError(ResultCodeEnum.PINGAN_SYSTEM_ERROR);
        }

        PinganAdapter.PinganResponse pinganResponse = null;
        try {
            pinganResponse = PinganAdapter.PinganResponse.parse(response.getData());
            log.info("PaymentLoanApiImpl#payFianceApplyStatus pinganResponse={}", JSON.toJSONString(pinganResponse));
        } catch (PaymentException e) {
            log.error("PaymentLoanApiImpl#payFianceApplyStatus invoke pingan error", e);
            return ResultVO.createError(ResultCodeEnum.PINGAN_SYSTEM_ERROR);
        }

        // 授信额度(单位分) 平安接口:单位：元，审批通过的时候才会返回
        String approveAmount = AmountCastUtil.castYuan2Fen(pinganResponse.getResultString("ApproveAmount")).toString();
        // 可用额度(单位分) 平安接口:单位：元，精确到分，建额成功的时候才会返回
        String availableAmount = AmountCastUtil.castYuan2Fen(pinganResponse.getResultString("AvailableAmount")).toString();
        log.info("PaymentLoanApiImpl.payFianceApplyStatus approveAmount {} availableAmount:{}", approveAmount, availableAmount);

        // 落地
//        payFinanceApply.setBecifId(resultJson.getString("BecifId"));
//        payFinanceApply.setContractNo(resultJson.getString("ContractNo"));
//        payFinanceApply.setApplyStatus(resultJson.getString("ApplyStatus"));
//        payFinanceApply.setAmountStartDate(resultJson.getString("AmountStartdate"));
//        payFinanceApply.setAmountEndDate(resultJson.getString("AmountEnddate"));
//        payFinanceApply.setApproveAmount(approveAmount);

        // 5.返回数据
        PinganLoanQueryApplyStatusVo loanQueryApplyStatusVo = PinganLoanQueryApplyStatusVo.builder()
                .approveAmount(approveAmount)
                .thirdApplyNo(thirdApplyNo)
                .businessUserId(payFinanceApply.getBusinessUserId())
                .businessUserName(payFinanceApply.getBusinessUserName())
                .businessType(payFinanceApply.getBusinessType())
                .becifId(payFinanceApply.getBecifId())
                .contractNo(payFinanceApply.getContractNo())
                .applyStatus(payFinanceApply.getApplyStatus())
                .amountStartDate(payFinanceApply.getAmountStartDate())
                .amountEndDate(payFinanceApply.getAmountEndDate())
                .denyReason(payFinanceApply.getDenyReason())
                .availableAmount(availableAmount)
                .build();

//        if (StringUtils.equals(loanQueryApplyStatusVo.getApplyStatus(), PinganLoanApplyStatusEnum.APPROVE_DENY.getCode())) {
//            payFinanceApply.setDenyReason(resultJson.getString("DenyReason"));
//            loanQueryApplyStatusVo.setDenyReason(resultJson.getString("DenyReason"));
//        }

//        pinganLoanFinanceApplyService.updateByPrimaryKeySelective(payFinanceApply);

        log.info("PaymentLoanApiImpl.payFianceApplyStatus result:{}", JSONUtils.toJSON(loanQueryApplyStatusVo));
        return ResultVO.createSuccess(loanQueryApplyStatusVo);
    }

    @Override
    public ResultVO<String> payFianceSendCustomerData(PinganLoanDatasToSendDto pinganLoanDatasToSendDto, String sign) {
        // 10.7 客户数据上送接口

        if (pinganLoanDatasToSendDto == null || StringUtils.isBlank(pinganLoanDatasToSendDto.getThirdApplyNo()) || pinganLoanDatasToSendDto.getSendType() == null) {
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
        }

        // 1.组装请求参数
        JSONObject requestParam = new JSONObject();
        requestParam.put("ThirdApplyNo", pinganLoanDatasToSendDto.getThirdApplyNo());
        requestParam.put("ProjectCode", ApolloUtil.getProperty("pingan.ProjectCode"));
        requestParam.put("ChannelCode", ApolloUtil.getProperty("pingan.ChannelCode"));
        requestParam.put("SendType", pinganLoanDatasToSendDto.getSendType().getCode());
        requestParam.put("IsMedicalLicenceRevoked", "N");
        JSONArray tableList = new JSONArray();
        requestParam.put("TableList", tableList);
        if (pinganLoanDatasToSendDto.getSendType() == PinganLoanDataSendTypeEnum.PRELOAN) {
            // 贷前
            putTableList(tableList, toMapListDataMerchantsInfo(pinganLoanDatasToSendDto.getDataMerchantsInfo()), PinganLoanDataTableNameEnum.MEDICINE_MERCHANTS_INFO_PRELOAN);
            putTableList(tableList, toMapListPinganLoanDataMonthlyOperation(pinganLoanDatasToSendDto.getDataMonthlyOperationList()), PinganLoanDataTableNameEnum.MEDICINE_MONTHLY_OPERATION_PRELOAN);
        } else {
            // 贷后
            putTableList(tableList, toMapListDataMerchantsInfo(pinganLoanDatasToSendDto.getDataMerchantsInfo()), PinganLoanDataTableNameEnum.MEDICINE_MERCHANTS_INFO_POSTLOAN);
            putTableList(tableList, toMapListPinganLoanDataMonthlyOperation(pinganLoanDatasToSendDto.getDataMonthlyOperationList()), PinganLoanDataTableNameEnum.MEDICINE_MONTHLY_OPERATION_POSTLOAN);
        }

        // 2.请求体
        SdkRequest sdkRequest = new SdkRequest();
        sdkRequest.setInterfaceName("V1.0/" + PinganMethod.LOAN_CUSTOMER_DATA.getMethodName());
        sdkRequest.setBody(requestParam);

        // 3.发送请求
        log.info("PaymentLoanApiImpl#payFianceSendCustomerData request:{}", JSONUtils.toJSON(requestParam));
        HttpResult response = apiClient.invoke(sdkRequest);
        log.info("PaymentLoanApiImpl#payFianceSendCustomerData request:{} response:{}", JSONUtils.toJSON(requestParam), JSONUtils.toJSON(response));

        // 4.通信状态判断
        if (response == null || !response.isSuccess()) {
            log.error("PaymentLoanApiImpl#payFianceSendCustomerData invoke pingan error, response isSuccess=false");
            return ResultVO.createError(ResultCodeEnum.PINGAN_SYSTEM_ERROR);
        }

        PinganAdapter.PinganResponse pinganResponse = null;
        try {
            pinganResponse = PinganAdapter.PinganResponse.parse(response.getData());
            log.info("PaymentLoanApiImpl#payFianceSendCustomerData pinganResponse={}", JSON.toJSONString(pinganResponse));
        } catch (PaymentException e) {
            log.error("PaymentLoanApiImpl#payFianceSendCustomerData invoke pingan error", e);
            return ResultVO.createError(ResultCodeEnum.PINGAN_SYSTEM_ERROR);
        }

        return ResultVO.createSuccess();
    }

    private void putTableList(JSONArray tableList, List<Map<String, Object>> dataInfoMapList, PinganLoanDataTableNameEnum dataTableNameEnum) {

        JSONObject tableInfo = new JSONObject();
        tableInfo.put("TableName", dataTableNameEnum.getCode());
        tableInfo.put("DataList", JSON.toJSONString(dataInfoMapList));
        tableList.add(tableInfo);
    }

    private List<Map<String, Object>> toMapListDataMerchantsInfo(PinganLoanDataMerchantsInfo info) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        map.put("PlatformNo", info.getPlatformNo());
        map.put("MerchantsName", info.getMerchantsName());
        map.put("CooperationYears", info.getCooperationYears());
        map.put("FixedBusinessPlace", info.getFixedBusinessPlace());
        map.put("IsRelatedCore", info.getIsRelatedCore());
        map.put("MerchantsType", info.getMerchantsType());
        map.put("CertificateExpireDate", info.getCertificateExpireDate());
        map.put("CertificateNo", info.getCertificateNo());
        map.put("IsMedicalLicenceRevoked", "N");
        map.put("StoresIsExceedTen", info.getStoreQty() < 10 ? "N" : "Y");
        mapList.add(map);
        return mapList;
    }

    private List<Map<String, Object>> toMapListPinganLoanDataMonthlyOperation(List<PinganLoanDataMonthlyOperation> dataMonthlyOperationList) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (PinganLoanDataMonthlyOperation info : dataMonthlyOperationList) {
            Map<String, Object> map = new HashMap<>();
            map.put("PlatformNo", info.getPlatformNo());
            map.put("Months", info.getMonths());
            map.put("MonthlyPurchaseAmount", info.getMonthlyPurchaseAmount());
            mapList.add(map);
        }
        return mapList;
    }

    @Override
    public ResultVO<PinganLoginTokenVo> getPinganLoginToken(String businessUserId) {

        try {

            if (StringUtils.isEmpty(businessUserId)) {
                log.warn("getPinganLoginToken 入参 param:businessUserId={}", businessUserId);
                return ResultVO.createError("businessUserId不能为空");
            }
//        pinganLoanFinanceApplyService
//        String userId = payAccountService.getAccountIdByBusiness(BusinessOrderTypeEnum.EC.getType(), businessUserId);

            String platformToken = leafUtil.getSnowflakeId();
            String bankToken = creditFinanceBankToken(platformToken, businessUserId);
            PinganLoginTokenVo vo = new PinganLoginTokenVo();
            if (StringUtils.isNotEmpty(bankToken)) {
                vo.setPlatformToken(platformToken);
                final String loginCheckUrl = pinganCreditLoginCheckUrl + "&bankToken=" + bankToken;
                vo.setPinganLoginCheckUrl(loginCheckUrl);
            }
            return ResultVO.createSuccess(vo);
        } catch (Exception e) {
            log.error("getPinganLoginToken error param:businessUserId={}", businessUserId, e);
            return ResultVO.createError("系统异常");
        }
    }

    @Override
    public ResultVO<XydCreditResultVo> searchCreditResult(Long merchantId, String uscc) {
        try {
            log.info("小雨点 7.1查询用户授信结果 param merchantId:{}, uscc:{}", merchantId, uscc);
            XydCreditResultDto xydCreditResultDto = xydLoanService.searchCreditResult(String.valueOf(merchantId), uscc);
            log.info("小雨点 7.1查询用户授信结果 result merchantId:{}", JSON.toJSONString(xydCreditResultDto));
            XydCreditResultVo xydCreditResultVo = new XydCreditResultVo();
            BeanUtils.copyProperties(xydCreditResultDto, xydCreditResultVo);
            return ResultVO.createSuccess(xydCreditResultVo);
        } catch (PaymentException e) {
            log.error("小雨点 7.1查询用户授信结果异常 param merchantId:{}, uscc:{}", merchantId, uscc, e);
            return ResultVO.createError("系统异常");
        }
    }

    public String creditFinanceBankToken(String platformToken, String userId) {
        try {
            JSONObject requestParam = new JSONObject();
            // 1.组装请求参数
            requestParam.put("ProjectCode", ApolloUtil.getProperty("pingan.ProjectCode"));
            requestParam.put("UserId", userId);
            requestParam.put("PlatformToken", platformToken);
            SdkRequest sdkRequest = new SdkRequest();
            sdkRequest.setInterfaceName("V1.0/" + PinganMethod.LOAN_BANK_TOKEN.getMethodName());
            sdkRequest.setBody(requestParam);

            // 3.发送请求
            log.info("creditFinanceBankToken request:{}", JSONUtils.toJSON(requestParam));
            HttpResult response = apiClient.invoke(sdkRequest);
            log.info("creditFinanceBankToken request:{} response:{}", JSONUtils.toJSON(requestParam), JSONUtils.toJSON(response));

            // 4.通信状态判断
            if (response == null || !response.isSuccess()) {
                log.error("PaymentLoanApiImpl#payFiancePreApply invoke pingan error, response isSuccess=false");
            }
            PinganAdapter.PinganResponse pinganResponse = PinganAdapter.PinganResponse.parse(response.getData());
            log.info("creditFinanceBankToken pinganResponse={}", JSON.toJSONString(pinganResponse));

            Map<String, Object> data = pinganResponse.getData();
            String bankToken = JSONObject.parseObject(JSONObject.toJSONString(data.get("Data"))).getString("BankToken");
            if (StringUtils.isNotEmpty(bankToken)) {
                if (StringUtils.isNotEmpty(bankToken)) {
                    return bankToken;
                }
            }
        } catch (PaymentException e) {
            log.error("creditFinanceBankToken invoke pingan error", e);
        }
        return "";
    }

    @Override
    public ResultVO<PinganLoanPreApplyResultVo> jdFiancePreApply(PinganLoanPreApplyParam param, String sign) {

        log.info("PaymentLoanApiImpl.jdFiancePreApply param:{}", JSONUtils.toJSON(param));

//         10.1 贷款申请接口
        if (param == null || StringUtils.isBlank(param.getBusinessUserId())) {
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
        }

        JSONObject requestParam = new JSONObject();
        String thirdApplyNo = leafUtil.getSnowflakeId();
        try {

            PayFinanceApply record = new PayFinanceApply();
            record.setThirdApplyNo(thirdApplyNo);
            record.setFinanceChannel(2);
            record.setBusinessUserId(param.getBusinessUserId());
            record.setBusinessUserName(param.getBusinessUserName());
            record.setBusinessType(param.getBusinessType());
            record.setApplyStatus(PinganLoanApplyStatusEnum.UN_PRE_APPLY.getCode());
            record.setCreateTime(new Date());
            record.setUpdateTime(new Date());

            int result = pinganLoanFinanceApplyService.insert(record);
            log.info("jdFiancePreApply result={}", result);
            if (result != 1) {
                return ResultVO.createError(ResultCodeEnum.DATABASE_ERROR);
            }

            return ResultVO.createSuccess(new PinganLoanPreApplyResultVo(thirdApplyNo, ""));
        } catch (Exception ex) {
            log.error("PaymentLoanApiImpl#payFiancePreApply error, param=" + JSONUtils.toJSON(requestParam) + ", errorMsg=" + ex.getMessage(), ex);
            return ResultVO.createError(ResultCodeEnum.PINGAN_SYSTEM_ERROR);
        }
    }

    @Override
    public ResultVO<AbchinaLoanPreApplyResultVo> abchinaLoanPreApply(AbchinaLoanPreApplyParam param) {
        String jsonParam = JSONUtils.toJSON(param);
        //log.info("PaymentLoanApiImpl.abchinaLoanPreApply param:{}", jsonParam);
        try {
            String thirdApplyNo = leafUtil.getSnowflakeId();
            PayFinanceApply record = new PayFinanceApply();
            record.setThirdApplyNo(thirdApplyNo);
            record.setFinanceChannel(FinanceChannelEnum.ABCHINA_LOAN.getCode());
            record.setBusinessUserId(param.getBusinessUserId());
            record.setBusinessUserName(param.getBusinessUserName());
            record.setBusinessType(param.getBusinessType());
            record.setApplyStatus(PinganLoanApplyStatusEnum.UN_PRE_APPLY.getCode());
            record.setLoanBalanceNo(param.getUscc());
            record.setCreateTime(new Date());
            record.setUpdateTime(new Date());
            int result = pinganLoanFinanceApplyService.insert(record);
            if (result != 1) {
                return ResultVO.createError(ResultCodeEnum.DATABASE_ERROR);
            }

            ApplyH5Dto applyH5Dto = new ApplyH5Dto()
                    .setUscc(param.getUscc())
                    .setUnitName(param.getBusinessUserName())
                    .setRegisterTime(param.getRegisterTime());
            String h5Url = abchinaLoanService.applyH5(applyH5Dto);

            PayFinanceApply payFinanceApplyQueryResult = pinganLoanFinanceApplyService.selectByThirdApplyNo(thirdApplyNo);
            PayFinanceApply payFinanceApplyUpdate = new PayFinanceApply();
            payFinanceApplyUpdate.setId(payFinanceApplyQueryResult.getId());
            payFinanceApplyUpdate.setApplyStatus(PinganLoanApplyStatusEnum.PRE_APPLY_SUCCESS.getCode());
            pinganLoanFinanceApplyService.updateByPrimaryKeySelective(payFinanceApplyUpdate);

            return ResultVO.createSuccess(new AbchinaLoanPreApplyResultVo().setH5Url(h5Url).setThirdApplyNo(thirdApplyNo));
        } catch (PayBizException pe) {
            log.error("PaymentLoanApiImpl#abchinaLoanPreApply peerror. param:{}", jsonParam, pe);
            return ResultVO.createErrorDisplayMsg(ResultCodeEnum.ABCHINA_LOAN_PREAPPLY_ERROR, pe.getMsg());
        } catch (Exception e) {
            log.error("PaymentLoanApiImpl#abchinaLoanPreApply error. param:{}", jsonParam, e);
            return ResultVO.createError(ResultCodeEnum.ABCHINA_LOAN_PREAPPLY_ERROR);
        }
    }

    @Override
    public ResultVO<AbchinaLoanNotifyApplyStatusVo> queryAbChinaLoanApplyState(AbchinaLoanQueryApplyParam param) {
        try {
            PayFinanceApply payFinanceApply = pinganLoanFinanceApplyService.findLatestRecordByLoanBalanceNo(param.getUscc(), FinanceChannelEnum.ABCHINA_LOAN.getCode());
            if (payFinanceApply == null) {
                throw new PayBizException("贷款申请记录不存在");
            }
            QueryLoanDto queryLoanDto = new QueryLoanDto()
                    .setUscc(param.getUscc());
            QueryLoanStatusResp queryLoanStatusResp = abchinaLoanService.queryLoanStatus(queryLoanDto);
            if (queryLoanStatusResp == null || StringUtils.isBlank(queryLoanStatusResp.getLoanStatus())) {
                throw new PayBizException("贷款申请状态查询，农行返回结果为空");
            }

            final PinganLoanApplyStatusEnum applyStatusEnum = AbchinaLoanStatusEnum.getPinganLoanApplyStatusEnum(queryLoanStatusResp.getLoanStatus());
            if (applyStatusEnum == null) {
                throw new PayBizException("贷款申请状态查询，农行返回状态未知");
            }

            payFinanceApply.setApplyStatus(applyStatusEnum.getCode());
            pinganLoanFinanceApplyService.updateByPrimaryKeySelective(payFinanceApply);

            AbchinaLoanNotifyApplyStatusVo abchinaLoanNotifyApplyStatusVo = new AbchinaLoanNotifyApplyStatusVo();
            abchinaLoanNotifyApplyStatusVo.setApplyStatus(applyStatusEnum);
            return ResultVO.createSuccess(abchinaLoanNotifyApplyStatusVo);
        } catch (PayBizException pe) {
            log.error("PaymentLoanApiImpl#queryAbChinaLoanApplyState peerror. param:{}", JSON.toJSONString(param), pe);
            return ResultVO.createErrorDisplayMsg(ResultCodeEnum.ABCHINA_LOAN_PREAPPLY_ERROR, pe.getMsg());
        } catch (Exception e) {
            log.error("PaymentLoanApiImpl#queryAbChinaLoanApplyState error. param:{}", JSON.toJSONString(param), e);
            return ResultVO.createError(ResultCodeEnum.ABCHINA_LOAN_PREAPPLY_ERROR);
        }
    }

    @Override
    public ResultVO<FinanceAccountInfoVo> queryFinanceAccountInfo(PinganLoanQueryApplyStatusParam param, String sign) {

        try {
            log.info("queryFinanceAccountInfo param:{}", JSONUtils.toJSON(param));

            // 10.5 融资状态查询接口
            if (param == null || StringUtils.isBlank(param.getThirdApplyNo())) {
                log.error("PaymentLoanApiImpl#queryFinanceAccountInfo param is null");
                return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
            }

            String thirdApplyNo = param.getThirdApplyNo();

            PayFinanceApply payFinanceApply = pinganLoanFinanceApplyService.selectByThirdApplyNo(thirdApplyNo);
            if (payFinanceApply == null) {
                log.error("PaymentLoanApiImpl#queryFinanceAccountInfo 支付平台申请编号不存在, param:{}", JSONUtils.toJSON(param));
                return ResultVO.createError("支付平台申请编号不存在");
            }
            FinanceAccountInfoVo financeAccountInfoVo = null;
            if (payFinanceApply.getFinanceChannel() == FinanceChannelEnum.PINGAN.getCode()) {
                financeAccountInfoVo = pinganAdapter.queryLoanAccountInfo(param);
            } else if (payFinanceApply.getFinanceChannel() == FinanceChannelEnum.JD_PURCHASE.getCode()) {
                financeAccountInfoVo = jdCreditAdapter.queryCustInfo(payFinanceApply.getBusinessUserId(), thirdApplyNo);
            } else if (payFinanceApply.getFinanceChannel() == FinanceChannelEnum.ABCHINA_LOAN.getCode()) {
                financeAccountInfoVo = abchinaLoanAdapter.queryLoanStatus(param.getUscc());
            } else if (payFinanceApply.getFinanceChannel() == FinanceChannelEnum.XYD_LOAN.getCode()) {
                financeAccountInfoVo = xydLoanAdapter.searchCreditResult(param.getBusinessUserId(), param.getUscc());
            }
            if (financeAccountInfoVo == null) {
                log.info("queryFinanceAccountInfo financeAccountInfoVo is null:{}", JSONObject.toJSONString(param));
                return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
            }
            // 5.返回数据
            financeAccountInfoVo.setBusinessUserId(payFinanceApply.getBusinessUserId());
            financeAccountInfoVo.setBusinessUserName(payFinanceApply.getBusinessUserName());
            financeAccountInfoVo.setBusinessType(payFinanceApply.getBusinessType());
            financeAccountInfoVo.setBecifId(payFinanceApply.getBecifId());
            financeAccountInfoVo.setContractNo(payFinanceApply.getContractNo());
            financeAccountInfoVo.setApplyStatus(payFinanceApply.getApplyStatus());
            financeAccountInfoVo.setAmountStartDate(payFinanceApply.getAmountStartDate());
            if (StringUtils.isEmpty(financeAccountInfoVo.getAmountEndDate())) {
                financeAccountInfoVo.setAmountEndDate(payFinanceApply.getAmountEndDate());
            }
            financeAccountInfoVo.setDenyReason(payFinanceApply.getDenyReason());
            financeAccountInfoVo.setThirdApplyNo(param.getThirdApplyNo());

            log.info("PaymentLoanApiImpl.payFianceApplyStatus result:{}", JSONUtils.toJSON(financeAccountInfoVo));
            return ResultVO.createSuccess(financeAccountInfoVo);
        } catch (Exception e) {
            log.error("queryFinanceAccountInfo error param:{}", JSONObject.toJSONString(param), e);
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        }
    }

    @Override
    public ResultVO<String> jdCreditSendCustomerData(PinganLoanDatasToSendDto param, String sign) {
        if (param == null || StringUtils.isBlank(param.getThirdApplyNo()) || param.getSendType() == null) {
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
        }
        ResultVO<String> resultVO = null;
        try {
            if (param.getChannel() == FinanceChannelEnum.PINGAN.getCode()) {
                resultVO = pinganAdapter.pushCustData(param);
            } else if (param.getChannel() == FinanceChannelEnum.JD_PURCHASE.getCode()) {
                resultVO = jdCreditAdapter.pushCustData(param);
            }
            return resultVO;
        } catch (PaymentException e) {
            log.error("payFianceSendCustomerData warn param ThirdApplyNo:{}", param.getThirdApplyNo(), e);
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR, e.getErrMsg());
        } catch (Exception e) {
            log.error("payFianceSendCustomerData error param ThirdApplyNo:{}", param.getThirdApplyNo(), e);
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        }

    }

    @Override
    public ResultVO<String> pushJdLoanSceneData(JDPushLoanSceneDto dto) {
        try {
            return jdCreditAdapter.pushLoanSceneData(dto);
        } catch (Exception e) {
            List<String> custCodeList = dto.getSceneDataList().stream().map(data -> data.getCustCode()).collect(Collectors.toList());
            if (e instanceof PaymentException) {
                log.error("payFianceSendCustomerData warn param custCodeList:{}", custCodeList, e);
                return ResultVO.createError(ResultCodeEnum.PARAM_ERROR, ((PaymentException) e).getErrMsg());
            } else {
                log.error("payFianceSendCustomerData error param custCodeList:{}", custCodeList, e);
                return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
            }
        }
    }

    @Override
    public ResultVO<String> pushXYDLoanSceneData(XYDPushLoanSceneDto xydPushLoanSceneDto) {
        try {
            log.info("小雨点 贷中数据推送 merchantId：{}, orderInfo:{}", xydPushLoanSceneDto.getMerchantId(), JSON.toJSONString(xydPushLoanSceneDto.getOrderList()));
            boolean flag = xydLoanAdapter.pushLoanSceneData(xydPushLoanSceneDto);
            if (flag) {
                return ResultVO.createSuccess();
            }
            return ResultVO.create(ResultCodeEnum.XYDLOAN_PUSH_ERROR);
        } catch (Exception e) {
            if (e instanceof PaymentException) {
                log.error("pushXYDLoanSceneData warn param xydPushLoanSceneDto:{}", xydPushLoanSceneDto, e);
                return ResultVO.createError(ResultCodeEnum.PARAM_ERROR, ((PaymentException) e).getErrMsg());
            } else {
                log.error("pushXYDLoanSceneData error param xydPushLoanSceneDto:{}", xydPushLoanSceneDto, e);
                return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
            }
        }
    }

    @Override
    public ResultVO<List<XydGetFileDto>> getXydCheckFile(String fileType, String checkDate, String checkCycle) {
        if (StringUtils.isEmpty(fileType) || StringUtils.isEmpty(checkDate) || StringUtils.isEmpty(checkCycle)) {
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
        }
        try {
            XydGetFileReq fileReq = new XydGetFileReq();
            fileReq.setFileType(fileType);
            fileReq.setCheckDate(checkDate);
            fileReq.setCheckCycle(checkCycle);
            List<XydGetFileDto> fileDtoList = xydLoanService.getFile(fileReq);
            return ResultVO.createSuccess(fileDtoList);
        } catch (Exception e) {
            log.error("getXydCheckFile error {}", fileType + "-" + checkDate);
            return ResultVO.createError("获取小雨点对账文件异常");
        }
    }

    @Override
    public ResultVO<XydAccountBalanceDto> queryXydAccountBalance(String accountNo) {
        if (StringUtils.isEmpty(accountNo)) {
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
        }
        try {
            XydAccountBalanceReq balanceReq = new XydAccountBalanceReq();
            balanceReq.setAccountNo(accountNo);
            return ResultVO.createSuccess(xydLoanService.queryAccountBalance(balanceReq));
        } catch (Exception e) {
            log.error("queryXydAccountBalance error accountNo:{}", accountNo);
            return ResultVO.createError("小雨点查询账户余额异常");
        }
    }
    @Override
    public ResultVO<JdCreditUnionLoginVo> jdCreditUnionLogin(JdCreditUnionLoginParam param, String sign) {

        try {
            JdCreditUnionLoginVo vo = unionLoginService.packingParams(param);
            return ResultVO.createSuccess(vo);
        } catch (Exception e) {
            log.error("jdCreditUnionLogin error param:{}", JSONObject.toJSONString(param), e);
            return ResultVO.createError(ResultCodeEnum.DEFAULT_ERROR);
        }
    }

    @Override
    public ResultVO<LoanPreApplyResultVo> preApply(LoanPreApplyParam param){
        log.info("##小雨点授信申请：preApply 入参：{}--", JSONObject.toJSONString(param));
        LoanPreApplyResultVo resultVo = new LoanPreApplyResultVo();
        //1、参数校验
        //2、申请表insert一条记录
        String thirdApplyNo = leafUtil.getSnowflakeId();
        PayFinanceApply record = new PayFinanceApply();
        record.setThirdApplyNo(thirdApplyNo);
        record.setFinanceChannel(FinanceChannelEnum.XYD_LOAN.getCode());
        record.setBusinessUserId(param.getBusinessUserId());
        record.setBusinessUserName(param.getBusinessUserName());
        record.setBusinessType(param.getBusinessType());
        record.setApplyStatus(PinganLoanApplyStatusEnum.UN_PRE_APPLY.getCode());
        record.setLoanBalanceNo(param.getUscc());
        record.setCreateTime(new Date());
        record.setUpdateTime(new Date());
        int result = pinganLoanFinanceApplyService.insert(record);
        if (result != 1) {
            return ResultVO.createError(ResultCodeEnum.DATABASE_ERROR);
        }
        //客户注册时间距离当前时间<180天，传“打新客户” NORMAL:正常客户； NEW:打新客户
        String orderTypeCode = "NORMAL";
        if (param.getMerchantCreateTime() != null) {
            long msNum = record.getCreateTime().getTime() - param.getMerchantCreateTime().getTime();
            long dayNum = msNum / (24 * 60 * 60 * 1000);
            if (dayNum < 180 && dayNum > 0) {
                orderTypeCode = "NEW";
            }
        }
        XydAuthCreditReq xydAuthCreditReq = new XydAuthCreditReq();
        xydAuthCreditReq.setAuth(new XydAuthCreditDto()
                .setDeviceNo(param.getBusinessUserId())
                .setThirdUserNo(param.getBusinessUserId())
                .setOuterOrderNo(thirdApplyNo)
                .setBusinessLicense(param.getUscc())
                .setOrderTypeCode(orderTypeCode)
        );
        xydAuthCreditReq.setPlatType("H5");
        log.info("##小雨点授信申请：authCredit 入参：{}--", JSONObject.toJSONString(xydAuthCreditReq));
        XydAuthCreditResp  resp = xydLoanService.authCredit(xydAuthCreditReq);
        log.info("##小雨点授信申请：authCredit 返回：{}--", JSONObject.toJSONString(resp));
        resultVo.setH5Url(resp.getH5Url());
        resultVo.setThirdApplyNo(thirdApplyNo);
        resultVo.setMsg(resp.getMsg());
        resultVo.setCode(resp.getCode());
        return ResultVO.createSuccess(resultVo);
    }
}
